package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.CurrencyDto;
import igor.lakienko.ru.generation.quotes.dto.MessageEventDto;
import igor.lakienko.ru.generation.quotes.entity.CurrencyEntity;
import igor.lakienko.ru.generation.quotes.enums.Currency;
import igor.lakienko.ru.generation.quotes.enums.RecommendationAnalysts;
import igor.lakienko.ru.generation.quotes.enums.TypeSecurities;
import igor.lakienko.ru.generation.quotes.mapper.CurrencyMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
class CurrencyServiceTest {

    @Mock
    CurrencyMapper currencyMapper;

    @InjectMocks
    CurrencyService currencyService;

    @BeforeEach
    void setUp() {
        getSizeBatchField();
    }

    @Test
    void whenGetCurrency_thenSuccessRandomCurrencyDto() {
        //given
        CurrencyDto currencyDefault = getCurrencyDefault();
        given(currencyMapper.currencyEntityToDto(any(CurrencyEntity.class))).willReturn(currencyDefault);

        //when
        MessageEventDto currency = currencyService.getCurrency();

        //then
        assertThat(currency).isEqualTo(currencyDefault);
    }

    @Test
    void whenGetCurrencies_thenSuccessRandomCurrencyDtos() {
        //given
        List<CurrencyDto> currencyDefault = List.of(getCurrencyDefault());
        given(currencyMapper.currenciesEntityToDto(anyList())).willReturn(currencyDefault);

        //when
        Collection<CurrencyDto> currencies = currencyService.getCurrencies();

        //then
        assertThat(currencies).isEqualTo(currencyDefault);
    }

    @SneakyThrows
    private void getSizeBatchField() {
        Field quoteSizeBatch = currencyService.getClass().getDeclaredField("currencySizeBatch");
        quoteSizeBatch.setAccessible(true);
        quoteSizeBatch.set(currencyService, 2);
    }

    private CurrencyDto getCurrencyDefault() {
        return CurrencyDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.STOCK)
                .currency(Currency.AUD_RUB)
                .bid(BigDecimal.ONE)
                .offer(BigDecimal.TEN)
                .fullCurrencyName(Currency.AUD_RUB.getDescription())
                .price(1_000.00F)
                .recommendationAnalysts(RecommendationAnalysts.SELL.getRecommendation())
                .yearlyVolatility(5.00F)
                .build();
    }

}
